import UIKit

var KS_SCREEN_WIDTH: CGFloat { get { return UIScreen.main.bounds.size.width } }
var KS_SCREEN_HEIGHT: CGFloat { get { return UIScreen.main.bounds.size.height } }
var KS_ONE_PIXEL: CGFloat { get { return 1.0 / UIScreen.main.scale } }
var KS_CalendarCellBackgroundColor: UIColor { get { return UIColor(red: 245/255.0, green: 245/255.0, blue: 245/255.0, alpha: 1.0) } }
var KS_TextColor: UIColor { get { return UIColor.black } }
var KS_WeekdayLabelTextColor: UIColor { get { return UIColor(red: 167/255.0, green: 167/255.0, blue: 167/255.0, alpha: 1.0) } }
var KS_MonthLabelTextColor: UIColor { get { return UIColor(red: 130/255.0, green: 130/255.0, blue: 130/255.0, alpha: 1.0) } }
var KS_NavigationBarColor: UIColor { get { return UIColor.red } }
var KS_TodayCalendarCellBackgroundColor: UIColor { get { return UIColor(red: 60/255.0, green: 60/255.0, blue: 60/255.0, alpha: 1.0) } }
var KS_SelectCalendarCellBackgroundColor: UIColor { get { return UIColor(red: 180/255.0, green: 180/255.0, blue: 180/255.0, alpha: 1.0) } }
var KS_SelectTextColor: UIColor { get { return UIColor.white } }
var KS_WeekendTextColor: UIColor { get { return UIColor.red } }
var KS_WeekdayViewHeight: CGFloat { get { return 20 } }
var KS_HeaderViewHeight: CGFloat { get { return 30 } }

protocol KSCalendarDelegate {
    func calendarViewSelectDate(_ startDate: String?, endDate: String?)
    func calendarViewSelectDate(_ date: String?)
}

extension KSCalendarDelegate {
    
    func calendarViewSelectDate(_ startDate: String?, endDate: String?) {
        
    }
    
    func calendarViewSelectDate(_ date: String?) {
        
    }
}

class KSCalendar: UIViewController {
    
    var isRadio = false
    /// 最大可选日期
    var maxSelectDate:String?
    /// 最小可选日期
    var minSelectDate:String?
    var subInfoDic: [String : String] = ["":""]
    var calendarViewSelectclosure:((String)->())?
    
    private var toolDate = ""
    private var startDate: Int?
    private var endDate: Int?
   
    private var pickerDate = Date() {
        didSet {
            
            /// 如果是同月 不刷新数据
            let formatter = DateFormatter()
            formatter.dateFormat = "yyyy年MM月"
            if datePickerFlag == formatter.string(from: pickerDate) {
                return
            }
            
            formatter.dateFormat = "yyyy-MM-dd"
            toolDate = formatter.string(from: pickerDate)
            datePickerFlag = String(toolDate[..<toolDate.index(toolDate.startIndex, offsetBy: 8)])
            dateLabel.setTitle(toolDate, for: UIControl.State())
            dataArray.removeAll()
            initDataSource()
            
            if let nonNilDelegate = delegate {
                nonNilDelegate.calendarViewSelectDate(toolDate)
            }
            if let closure = calendarViewSelectclosure {
                closure(toolDate)
            }
        }
    }
    private var datePickerFlag = ""
    private var bottomView: UIView!
    private var datePicker: UIDatePicker!
    private var dateLabel: UIButton!
    
    private var dataArray = [KSCalendarHeaderModel]() {
        didSet {
            
            UIView.animate(withDuration: 0.25, animations: {
                self.collectionView.reloadData()
            })
        }
    }
    
    private var weekArray = [[KSCalendarModel]]()
    private var collectionView: UICollectionView!
    
    var delegate: KSCalendarDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        initDataSource()
        createUI()
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return UIStatusBarStyle.lightContent
    }
    
    private func initDataSource() {
        
        DispatchQueue.global().async {
            let manager = KSCalendarManager(startDate: self.pickerDate)
            let tempDataArray = manager.getCalendarDataSourceWithLimitMonth()
            
            DispatchQueue.main.async(execute: {
                self.dataArray = tempDataArray
                if let indexPath = manager.startIndexPath {
                    self.showCollectionViewWithStartIndexPath(indexPath)
                }
            })
        }
    }
    
    private func createUI() {
        
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        toolDate = formatter.string(from: Date())
        
        self.title =  "日 历"
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "返回", style: .done, target: self, action: #selector(navigationBackButton))
        
        
        
        addWeekdayView()
        
        let width = UIScreen.main.bounds.width / 8
        let height = width
        
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.itemSize = CGSize(width: width, height: height)
        flowLayout.headerReferenceSize = CGSize(width: KS_SCREEN_WIDTH, height: KS_HeaderViewHeight)
        flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        flowLayout.minimumInteritemSpacing = 0
        flowLayout.minimumLineSpacing = 0
        flowLayout.sectionHeadersPinToVisibleBounds = true
        
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = UIColor.white
        collectionView.showsVerticalScrollIndicator = false
        view.addSubview(collectionView)
        
        collectionView.register(KSCalendarCell.self, forCellWithReuseIdentifier: "KSCalendarCell")
        collectionView.register(KSCalendarReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "KSCalendarReusableView")
        
        addDatePicker()
    }
    
    private func addWeekdayView() {
        
        let weekdayView = UIView(frame: CGRect(x: 0, y: 64, width: KS_SCREEN_WIDTH, height: KS_WeekdayViewHeight))
        weekdayView.backgroundColor = UIColor(red: 248/255.0, green: 248/255.0, blue: 248/255.0, alpha: 1.0)
        view.addSubview(weekdayView)
        let weekdayArray = ["周次", "周一", "周二", "周三", "周四", "周五", "周六", "周日"]
        let width = UIScreen.main.bounds.width / 8
        for i in 0..<8 {
            let weekdayLabel = UILabel(frame: CGRect(x: CGFloat(i) * width, y: 0, width: width, height: KS_WeekdayViewHeight))
            weekdayLabel.text = weekdayArray[i]
            weekdayLabel.font = UIFont.boldSystemFont(ofSize: 12)
            weekdayLabel.textAlignment = .center
            weekdayLabel.textColor = KS_WeekdayLabelTextColor
            weekdayView.addSubview(weekdayLabel)
        }
    }
    
    private func addDatePicker() {
        
        bottomView = UIView(frame: CGRect(x: 0, y: self.view.frame.maxY - 64, width: KS_SCREEN_WIDTH, height: 64))
        
        bottomView.backgroundColor = KS_CalendarCellBackgroundColor
        let todayButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: bottomView.frame.height))
        todayButton.setTitleColor(UIColor(red: 68/255.0, green: 192/255.0, blue: 255/255.0, alpha: 1.0), for: UIControl.State())
        todayButton.setTitle("今天", for: UIControl.State())
        todayButton.addTarget(self, action: #selector(todayButtonClick), for: .touchUpInside)
        bottomView.addSubview(todayButton)
        
        dateLabel = UIButton(frame: CGRect(x: 60, y: 0, width: KS_SCREEN_WIDTH - 120, height: bottomView.frame.height))
        
        dateLabel.setTitle(toolDate, for: UIControl.State())
        dateLabel.setTitleColor(UIColor(red: 68/255.0, green: 192/255.0, blue: 255/255.0, alpha: 1.0), for: UIControl.State())
        dateLabel.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
        dateLabel.addTarget(self, action: #selector(setDateButtonClick), for: .touchUpInside)
        bottomView.addSubview(dateLabel)
        
        let doneButton = UIButton(frame: CGRect(x: KS_SCREEN_WIDTH - 60, y: 0, width: 60, height: bottomView.frame.height))
        doneButton.setTitleColor(UIColor(red: 68/255.0, green: 192/255.0, blue: 255/255.0, alpha: 1.0), for: UIControl.State())
        doneButton.setTitle("完成", for: UIControl.State())
        doneButton.addTarget(self, action: #selector(doneButtonClick), for: .touchUpInside)
        bottomView.addSubview(doneButton)
        
        datePicker = UIDatePicker()
        if #available(iOS 13.4, *) {
            self.datePicker.preferredDatePickerStyle = .wheels
        } else {
            
        }
  
      
        datePicker.backgroundColor = UIColor.white
        datePicker.datePickerMode = .date
        datePicker.date = Date()
        datePicker.locale = Locale(identifier: "zh")
        datePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged)
        datePicker.frame = CGRect(x: 0, y: KS_SCREEN_HEIGHT, width: KS_SCREEN_WIDTH, height: 216)
        
        view.addSubview(datePicker)
        view.addSubview(bottomView)
    }
    
    @objc private func navigationBackButton() {
        dismiss(animated: true, completion: nil)
    }
    
    @objc private func datePickerValueChanged(_ picker: UIDatePicker) {
        pickerDate = picker.date
    }
    
    @objc private func todayButtonClick() {
        pickerDate = Date()
        scalingDatePicker(CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 64), datePickerPoint: CGPoint(x: 0, y: KS_SCREEN_HEIGHT))
    }
    
    @objc private func doneButtonClick() {
        
        if let max = maxSelectDate {
            if toolDate > max {
                KSToast("超过最大可选日期")
                return
            }
            
        }
        if let min = minSelectDate {
            if toolDate < min {
                KSToast("超过最小可选日期")
                return
            }
            
        }
        
        if let nonNilDelegate = delegate {
            nonNilDelegate.calendarViewSelectDate(toolDate)
        }
        if let closure = calendarViewSelectclosure {
            closure(toolDate)
        }
        
        
        scalingDatePicker(CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 64), datePickerPoint: CGPoint(x: 0, y: KS_SCREEN_HEIGHT))
        dismiss(animated: true, completion: nil)
    }
    
    @objc private func setDateButtonClick() {
        scalingDatePicker(CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 216 - 64), datePickerPoint: CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 216))
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        scalingDatePicker(CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 64), datePickerPoint: CGPoint(x: 0, y: KS_SCREEN_HEIGHT))
    }
    
    /// 缩放时间选择器
    private func scalingDatePicker(_ bottomViewPoint: CGPoint, datePickerPoint: CGPoint) {
        UIView.animate(withDuration: 0.2, delay: 0.0, options: [.allowUserInteraction, .curveLinear], animations: { () -> Void in
            self.bottomView.frame.origin = bottomViewPoint
        }, completion: { (_) -> Void in
        })
        
        UIView.animate(withDuration: 0.2, delay: 0.0, options: [.allowUserInteraction, .curveLinear], animations: { () -> Void in
            self.datePicker.frame.origin = datePickerPoint
        }, completion: { (_) -> Void in
        })
        
    }
    
    /// 滚动到选中时间的当月
    private func showCollectionViewWithStartIndexPath(_ startIndexPath: IndexPath) {
        collectionView.scrollToItem(at: startIndexPath, at: UICollectionView.ScrollPosition.top, animated: false)
        collectionView.contentOffset = CGPoint(x: 0, y: collectionView.contentOffset.y - KS_HeaderViewHeight)
    }
    
    private func dateToString(_ date: Int) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        return dateFormatter.string(from: Date(timeIntervalSince1970: Double(date)))
    }
    
    override var shouldAutorotate: Bool {
        return true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return UIInterfaceOrientation.portrait
    }
}

extension KSCalendar: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return dataArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataArray[section].calendarItemArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "KSCalendarCell", for: indexPath) as! KSCalendarCell
        let headerItem = dataArray[indexPath.section]
        let calendarItem = headerItem.calendarItemArray[indexPath.row]
        
        /// 显示周次
        if indexPath.row % 8 == 0 {
            cell.ifSelected = false
            cell.dateLabel.text = String(calendarItem.weekOfYear)
            cell.dateLabel.textColor = KS_TextColor
            cell.subLabel.textColor = KS_TextColor
            cell.subLabel.text = ""
            cell.dateLabel.font = UIFont.boldSystemFont(ofSize: 20)
            cell.cellBackgroundView.backgroundColor = KS_CalendarCellBackgroundColor
            cell.isUserInteractionEnabled = true
        } else if calendarItem.day > 0 {
            
            cell.ifSelected = false
            cell.dateLabel.text = String(calendarItem.day)
            cell.dateLabel.font = UIFont.systemFont(ofSize: 15)
            cell.dateLabel.textColor = KS_TextColor
            cell.subLabel.textColor = KS_TextColor
            let dateDes = dateToString(calendarItem.dateInterval)
            cell.subLabel.text = subInfoDic[dateDes]
            cell.cellBackgroundView.backgroundColor = KS_CalendarCellBackgroundColor
            cell.isUserInteractionEnabled = true
            
            if calendarItem.dateInterval == startDate {
                cell.ifSelected = true
                cell.dateLabel.textColor = KS_SelectTextColor
                cell.subLabel.textColor = KS_SelectTextColor
            } else if calendarItem.dateInterval == endDate {
                cell.ifSelected = true
                cell.dateLabel.textColor = KS_SelectTextColor
                cell.subLabel.textColor = KS_SelectTextColor
            } else {
                if let start = startDate, let end = endDate {
                    if calendarItem.dateInterval > start && calendarItem.dateInterval < end {
                        cell.ifSelected = true
                        cell.dateLabel.textColor = KS_SelectTextColor
                        cell.subLabel.textColor = KS_SelectTextColor
                    }
                }
            }
            
            if calendarItem.type == .todayType {
                cell.cellBackgroundView.backgroundColor = KS_TodayCalendarCellBackgroundColor
                cell.dateLabel.textColor = KS_SelectTextColor
                cell.subLabel.textColor = KS_SelectTextColor
            }
            
        } else {
            cell.dateLabel.text = ""
            cell.subLabel.text = ""
            cell.ifSelected = false
            cell.cellBackgroundView.backgroundColor = UIColor.white
            cell.dateLabel.textColor = KS_TextColor
            cell.isUserInteractionEnabled = false
        }
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        scalingDatePicker(CGPoint(x: 0, y: KS_SCREEN_HEIGHT - 64), datePickerPoint: CGPoint(x: 0, y: KS_SCREEN_HEIGHT))
        
        let headerItem = dataArray[indexPath.section]
        let calendarItem = headerItem.calendarItemArray[indexPath.row]
        
        if isRadio {
            
            startDate = calendarItem.dateInterval
            
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd"
            
            if let tempDate = startDate {
                let date = dateToString(tempDate)
                dateLabel.setTitle(date, for: UIControl.State())
                toolDate = date
                // 单纯选择，不要赋值，点了确定再赋值
//                if let nonNilDelegate = delegate, date != "1970-01-01" {
//                    nonNilDelegate.calendarViewSelectDate(date)
//                }
//                if let closure = calendarViewSelectclosure {
//                    closure(toolDate)
//                }
            }
        } else {
            /// 根据周次取选择时间段
            if indexPath.row % 8 == 0 {
                var dayOfOneWeekArray = [KSCalendarModel]()
                if calendarItem.weekInMonthType == .first {
                    guard indexPath.section != 0 else {
                        return
                    }
                    let lastMonthCalendarItem = dataArray[indexPath.section - 1]
                    dayOfOneWeekArray = addSameWeekArray(lastMonthCalendarItem, item: calendarItem, calendarArray: dayOfOneWeekArray)
                    dayOfOneWeekArray = addSameWeekArray(headerItem, item: calendarItem, calendarArray: dayOfOneWeekArray)
                } else if calendarItem.weekInMonthType == .last {
                    guard indexPath.section < dataArray.count - 1 else {
                        return
                    }
                    let nextMonthCalendarItem = dataArray[indexPath.section + 1]
                    dayOfOneWeekArray = addSameWeekArray(headerItem, item: calendarItem, calendarArray: dayOfOneWeekArray)
                    dayOfOneWeekArray = addSameWeekArray(nextMonthCalendarItem, item: calendarItem, calendarArray: dayOfOneWeekArray)
                } else {
                    dayOfOneWeekArray = addSameWeekArray(headerItem, item: calendarItem, calendarArray: dayOfOneWeekArray)
                }
                
                if weekArray.count == 0 {
                    weekArray.append(dayOfOneWeekArray)
                } else {
                    let firstObjectWeekArray = weekArray.first
                    let lastObjectWeekArray = weekArray.last
                    
                    /// 取firstObjectWeekArray[1]的原因是:firstObjectWeekArray[0]是用于显示周次的，没有时间戳
                    let startDateInWeek = firstObjectWeekArray![1].dateInterval
                    let endDateInWeek = lastObjectWeekArray?.last?.dateInterval
                    
                    let tempStartDate = dayOfOneWeekArray[1].dateInterval
                    let tempEndDate = dayOfOneWeekArray.last?.dateInterval
                    
                    if tempStartDate < startDateInWeek {
                        weekArray.insert(dayOfOneWeekArray, at: 0)
                    } else if tempEndDate! > endDateInWeek! {
                        weekArray.append(dayOfOneWeekArray)
                    }
                }
                
                if let tempDate = weekArray.first?[1].dateInterval {
                    startDate = tempDate
                }
                
                if let tempDate = weekArray.last?.last?.dateInterval {
                    endDate = tempDate
                }
                
                if let nonNilDelegate = delegate {
                    
                    let sdate = dateToString(startDate!)
                    let edate = dateToString(endDate!)
                    nonNilDelegate.calendarViewSelectDate(sdate, endDate: edate)
                }
                
            } else {
                weekArray.removeAll()
                
                /// 根据起始时间和结束时间选择时间段
                if startDate == nil {
                    startDate = calendarItem.dateInterval
                    
                } else if startDate != nil && endDate != nil {
                    startDate = calendarItem.dateInterval
                    endDate = nil
                } else {
                    endDate = calendarItem.dateInterval
                    if startDate! > endDate! {
                        let tempDate = startDate
                        startDate = endDate
                        endDate = tempDate
                    }
                    
                }
                
                if let nonNilDelegate = delegate {
                    if let start = startDate, let end = endDate {
                        let sdate = dateToString(start)
                        let edate = dateToString(end)
                        nonNilDelegate.calendarViewSelectDate(sdate, endDate: edate)
                    }
                }
            }
            
        }
        collectionView.reloadData()
    }
    
    /// 添加header视图
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        var reusableView: UICollectionReusableView!
        if kind == UICollectionView.elementKindSectionHeader {
            let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "KSCalendarReusableView", for: indexPath) as! KSCalendarReusableView
            let headerItem = dataArray[indexPath.section]
            headerView.headerLabel.text = headerItem.headerText
            reusableView = headerView
        }
        return reusableView
    }
    
    private func addSameWeekArray(_ headerItem: KSCalendarHeaderModel, item: KSCalendarModel, calendarArray: [KSCalendarModel]) -> [KSCalendarModel] {
        var resultArray = calendarArray
        for temp in headerItem.calendarItemArray {
            if temp.weekOfYear == item.weekOfYear {
                resultArray.append(temp)
            }
        }
        return resultArray
    }
}

class KSCalendarCell: UICollectionViewCell {
    
    var dateLabel: UILabel!
    var cellBackgroundView: UIView!
    var ifSelected: Bool? {
        didSet {
            if ifSelected! {
                cellBackgroundView.backgroundColor = KS_SelectCalendarCellBackgroundColor
            } else {
                cellBackgroundView.backgroundColor = KS_CalendarCellBackgroundColor
            }
        }
    }
    
    var subLabel: UILabel!
    private var imageView: UIImageView?
  
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        createCell()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fatalError("init(coder:) has not been implemented")
    }
    
    private func createCell() {
        cellBackgroundView = UIView(frame: CGRect(x: 1, y: 1, width: frame.width - 1, height: frame.height - 1))
        contentView.addSubview(cellBackgroundView)
        
        dateLabel = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height - 11))
        dateLabel.textAlignment = .center
        dateLabel.font = UIFont.systemFont(ofSize: 15)
        contentView.addSubview(dateLabel)
 
        subLabel = UILabel(frame: CGRect(x: 0, y: frame.height - 20, width: frame.width, height: 20))
        subLabel.textAlignment = .center
        subLabel.font = UIFont.systemFont(ofSize: 10)
        contentView.addSubview(subLabel)
        
    }
}

class KSCalendarReusableView: UICollectionReusableView {
    var headerLabel: UILabel!
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        createReusableView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        fatalError("init(coder:) has not been implemented")
    }
    
    private func createReusableView() {
        
        let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
        headerView.backgroundColor = UIColor(red: 248/255.0, green: 248/255.0, blue: 248/255.0, alpha: 0.8)
        addSubview(headerView)
        
        headerLabel = UILabel(frame: CGRect(x: frame.width / 2 - 45, y: 0, width: 90, height: frame.height))
        headerLabel.textAlignment = .center
        headerLabel.textColor = KS_MonthLabelTextColor
        headerLabel.font = UIFont.boldSystemFont(ofSize: 14)
        headerLabel.backgroundColor = UIColor.clear
        headerView.addSubview(headerLabel)
    }
}

enum KSCalendarType {
    case todayType, lastType, nextType, other
}

/// 单月中周次的位置
///
/// - first: 每月第一周
/// - middle: 每月中间周次
/// - last: 每月最后一周
enum KSWeekInMonthType {
    case first, middle, last
}

class KSCalendarHeaderModel: NSObject {
    var headerText: String!
    var calendarItemArray: [KSCalendarModel]!
}

class KSCalendarModel: NSObject {
    var dateInterval: Int = 0
    var year: Int = 0
    var month: Int = 0
    var day: Int = 0
    var weekOfYear: Int = 0
    var weekday: Int = 0
    var weekInMonthType: KSWeekInMonthType = .middle
    var type: KSCalendarType = .other
}

class KSCalendarManager: NSObject {
    
    var startIndexPath: IndexPath?
    private var todayDate: Date!
    private var todayCompontents: DateComponents!
    private var greCalendar: Calendar!
    private var dateFormatter: DateFormatter!
    private var startDate: Int!
    private var pickerDate: Date!
    
    init(startDate: Date) {
        super.init()
        greCalendar = Calendar(identifier: Calendar.Identifier.gregorian)
        greCalendar.firstWeekday = 2
        todayDate = Date()
        todayCompontents = dateToComponents(todayDate)
        dateFormatter = DateFormatter()
        pickerDate = startDate
        self.startDate = dateToInterval(greCalendar.date(from: dateToComponents(startDate))!)
    }
    
    /// 计算每一天数据
    /// limitMonth: 月的长度
    /// - Returns: 返回所有月的数据
    func getCalendarDataSourceWithLimitMonth() -> [KSCalendarHeaderModel] {
        
        var resultArray = [KSCalendarHeaderModel]()
        var components = dateToComponents(pickerDate)
        /// 限制月份 设置当前日期前后可以查到的月份
        let limitMonth = 12 * 200
        
        components.day = 1
        components.month = components.month! - (limitMonth + 1) / 2
        
        for item in 0..<limitMonth {
            components.month = components.month! + 1
            let headerItem = KSCalendarHeaderModel()
            let date = greCalendar.date(from: components)!
            dateFormatter.dateFormat = "yyyy年MM月"
            let dateString = dateFormatter.string(from: date)
            headerItem.headerText = dateString
            headerItem.calendarItemArray = getCalendarItemArrayWithDate(date, section: item)
            resultArray.append(headerItem)
        }
        return resultArray
    }
    
    /// 计算单月每一天数据
    ///
    /// - Parameters:
    ///   - date: 每一月的第一天
    ///   - section: 第几个月
    /// - Returns: 返回单个月所有天数的数组
    private func getCalendarItemArrayWithDate(_ date: Date, section: Int) -> [KSCalendarModel] {
        
        var resultArray = [KSCalendarModel]()
        var components = dateToComponents(date)
        
        let weeksOfYear = numberOfWeeksInCurrentYear(date)
        let tatalDay = numberOfDaysInCurrentMonth(date)
        let firstDay = startDayOfWeek(date)
        
        ///  判断日历每月多少列
        let tempDay = tatalDay + firstDay - 8
        var column = 0
        if tempDay % 7 == 0 {
            column = tempDay / 7 + 1
        } else {
            column = tempDay / 7 + 2
        }
        
        components.day = 0
        for i in 0..<column {
            for j in 0..<8 {
                let calendarItem = KSCalendarModel()
                /// 当前周次
                let tempValue = components.weekOfYear! + i
                if j == 0 {
                    // MARK: - 这里还有问题
                    /// 将年末没有满星期的周次设置为来年的第一周
                    
                    // 53、 54周
                    //                    if tempValue == weeksOfYear {
                    //                        calendarItem.weekOfYear = 1
                    //                    } else {
                    calendarItem.weekOfYear = tempValue
                    //                    }
                    
                    switch i {
                    case 0:
                        calendarItem.weekInMonthType = .first
                    case column - 1:
                        calendarItem.weekInMonthType = .last
                    default:
                        calendarItem.weekInMonthType = .middle
                    }
                    
                    resultArray.append(calendarItem)
                    continue
                } else if i == 0 && j < firstDay {
                    calendarItem.year = 0
                    calendarItem.month = 0
                    calendarItem.day = 0
                    calendarItem.weekday = -1
                    calendarItem.dateInterval = -1
                    resultArray.append(calendarItem)
                    continue
                } else {
                    components.day = components.day! + 1
                    
                    guard components.day != tatalDay + 1 else { break }
                    
                    calendarItem.year = components.year!
                    calendarItem.month = components.month!
                    calendarItem.day = components.day!
                    calendarItem.weekday = j
                    
                    if calendarItem.year == todayCompontents.year &&
                        calendarItem.month == todayCompontents.month &&
                        calendarItem.day == todayCompontents.day {
                        calendarItem.type = .todayType
                    }
                    
                    if tempValue == weeksOfYear {
                        /// 当年的最后一周是完整的一周周次为当年的最后一周，否则算来年的第一周
                        if calendarItem.weekday == 7 {
                            calendarItem.weekOfYear = tempValue
                            for index in resultArray.count - 7..<resultArray.count {
                                resultArray[index].weekOfYear = tempValue
                            }
                        } else {
                            calendarItem.weekOfYear = 1
                        }
                    } else {
                        calendarItem.weekOfYear = tempValue
                    }
                    
                    let date = greCalendar.date(from: components)
                    calendarItem.dateInterval = dateToInterval(date!)
                    
                    if startDate == calendarItem.dateInterval {
                        startIndexPath = IndexPath(row: 0, section: section)
                    }
                    
                    resultArray.append(calendarItem)
                }
            }
        }
        return resultArray
    }
    
    private func dateToComponents(_ date: Date) -> DateComponents {
        
        return greCalendar.dateComponents([.year,
                                           .month,
                                           .day,
                                           .weekOfYear,
                                           .weekday], from: date)
    }
    
    /// 计算一个月多少天
    private func numberOfDaysInCurrentMonth(_ date: Date) -> Int {
        return (greCalendar.range(of: Calendar.Component.day, in: Calendar.Component.month, for: date)?.count)!
    }
    
    ///  计算一个年多少周
    private func numberOfWeeksInCurrentYear(_ date: Date) -> Int {
        return (greCalendar.range(of: Calendar.Component.weekOfYear, in: Calendar.Component.year, for: date)?.count)!
    }
    
    /// 计算这个月的第一天星期几
    private func startDayOfWeek(_ date: Date) -> Int {
        
        var startDate = Date()
        var interval = TimeInterval()
        let result: Bool = greCalendar.dateInterval(of: Calendar.Component.month, start: &startDate, interval: &interval, for: date)
        
        if let s = greCalendar.ordinality(of: Calendar.Component.day, in: Calendar.Component.weekOfYear, for: startDate), result {
            return s
        } else {
            return 0
        }
    }
    
    func dateToInterval(_ date: Date) -> Int {
        return Int(date.timeIntervalSince1970)
    }
}
